﻿using System;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.Web.Services.Protocols;
using EconomicInformationServiceWcf.Helpers;
using Framework.Security;

namespace EconomicInformationServiceWcf.ServiceBehaviours
{
    [AttributeUsage(AttributeTargets.Interface)]
    public class EISHeadersAttribute :  Attribute, IWsdlExportExtension, IContractBehavior
    {
        public void ExportContract(WsdlExporter exporter, WsdlContractConversionContext context)
        {
            ExportHeaderContract(exporter, context);
        }

        public void ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context)
        {}

        #region IContract behaviour inplementation

        public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
        {}

        public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint,
                                          DispatchRuntime dispatchRuntime)
        {}

        public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {}

        public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint,
                                         BindingParameterCollection bindingParameters)
        { }

        #endregion

        internal static void ExportHeaderContract(WsdlExporter exporter, WsdlContractConversionContext context)
        {
            foreach (OperationDescription op in context.Contract.Operations)
            {
                var soapHeaders = (EISHeaderAttribute[])op.SyncMethod.GetCustomAttributes(typeof(EISHeaderAttribute), false);
                if (soapHeaders.Length > 0)
                {
                    foreach (var soapHeader in soapHeaders)
                        AddSoapHeader(context.Contract.Namespace, op, soapHeader);
                }
            }
        }

        internal static void AddSoapHeader(string contractNamespace, OperationDescription op, EISHeaderAttribute soapHeader)
        {
            var headerNamespace = SoapHeaderHelper.GetNamespace(soapHeader.Type);
            if (headerNamespace == string.Empty && contractNamespace != string.Empty)
                headerNamespace = contractNamespace;

            var header = new MessageHeaderDescription(soapHeader.Name, headerNamespace) {Type = soapHeader.Type};
            bool input = ((soapHeader.Direction & SoapHeaderDirection.In) == SoapHeaderDirection.In);
            bool output = ((soapHeader.Direction & SoapHeaderDirection.Out) == SoapHeaderDirection.Out);

            foreach (MessageDescription msgDescription in op.Messages)
            {
                if ((msgDescription.Direction == MessageDirection.Input && input) ||
                    (msgDescription.Direction == MessageDirection.Output && output))
                    msgDescription.Headers.Add(header);
            }
        }
    }
}